//======================================================================
//    We will gone,the word kept  
//======================================================================
`timescale 1ns/1ps
//generate by AI
module fifo_tb
#(  parameter FWFT_EN = "FALSE",
   parameter OUTREG_EN = "FALSE",
   parameter ASY_CLK_ENB = "TRUE"
);
    parameter DATA_WIDTH = 16;
    parameter ADDR_WIDTH = 4;
    parameter PROG_EMPTY = 4;
    parameter PROG_FULL = 12;
    
    reg wr_clk, rd_clk;
    wire wclk, rclk;
    reg wr_rst, rd_rst;
    reg [DATA_WIDTH-1:0] din;
    reg wr_en, rd_en;
    wire [DATA_WIDTH-1:0] dout;
    wire full, empty;
    wire almost_full, almost_empty;
    reg[7:0]  count = 0;
    generate
        if (ASY_CLK_ENB=="TRUE") begin
           assign wclk =wr_clk ;
           assign rclk = rd_clk ;
        end else begin
           assign wclk =wr_clk ;
           assign rclk = wr_clk ;
        end

    endgenerate
            // 实例化被测模块
            fifo #(
                .DATA_WIDTH(DATA_WIDTH),
                .ADDR_WIDTH(ADDR_WIDTH),
                .PROG_EMPTY(PROG_EMPTY),
                .PROG_FULL(PROG_FULL),
                .ASY_CLK_ENB("TRUE")  // 测试异步模式
            ) dut (
                .wr_rst(wr_rst),
                .rd_rst(rd_rst),
                .wr_clk(wclk),
                .rd_clk(rclk),
                .din(din),
                .wr_en(wr_en),
                .rd_en(rd_en),
                .dout(dout),
                .full(full),
                .empty(empty),
                .rd_data_count   (),
                .wr_data_count   (),
                .almost_empty(almost_empty),
                .almost_full(almost_full)
            );
        /*else
            // 实例化被测模块
            fifo #(
                .DATA_WIDTH(DATA_WIDTH),
                .ADDR_WIDTH(ADDR_WIDTH),
                .PROG_EMPTY(PROG_EMPTY),
                .PROG_FULL(PROG_FULL),
                .ASY_CLK_ENB("FALSE")  // 测试异步模式
            ) dut (
                .wr_rst(wr_rst),
                .rd_rst(rd_rst),
                .wr_clk(wr_clk),
                .rd_clk(wr_clk),
                .din(din),
                .wr_en(wr_en),
                .rd_en(rd_en),
                .dout(dout),
                .full(full),
                .empty(empty),
                .rd_data_count   (),
                .wr_data_count   (),
                .almost_empty(almost_empty),
                .almost_full(almost_full)
            );
    endgenerate
    */
    
    // 时钟生成（不同频率测试异步模式）
    initial begin
        wr_clk = 0;
        forever #10 wr_clk = ~wr_clk;  // 50MHz写时钟
    end
    
    initial begin
        rd_clk = 0;
        forever #15 rd_clk = ~rd_clk;  // ~33MHz读时钟
    end
    
    // 测试控制
    initial begin
        // 复位初始化
        wr_rst = 1; rd_rst = 1;
        wr_en = 0; rd_en = 0;
        din = 0;
        #100;
        wr_rst = 0; rd_rst = 0;
        
        // 阶段1：连续写操作
        $display("=== 阶段1：连续写入测试 ===");
        for(int i=0; i<20; i++) begin
            @(negedge wclk);
            wr_en = ~full;
            din = {count[3:0],count[3:0]+1,count};//$random;
            if(full) break;
        end
        wr_en = 0;
        
        // 阶段2：连续读操作
        #100;
        $display("=== 阶段2：连续读取测试 ===");
        repeat(20) begin
            @(negedge rclk);
            rd_en = ~empty;
            #1; // 等待信号稳定
            if(empty) break;
            $display("读出数据：%h", dout);
        end
        rd_en = 0;
        
        // 阶段3：随机读写混合测试
        #100;
        $display("=== 阶段3：随机混合测试 ===");
        fork
            // 写进程
            begin
                repeat(50) begin
                    @(negedge wclk);
                    wr_en = $urandom_range(0,1) & ~full;
                    din = $random;
                end
                wr_en = 0;
            end
            
            // 读进程
            begin
                repeat(50) begin
                    @(negedge rclk);
                    rd_en = $urandom_range(0,1) & ~empty;
                end
                rd_en = 0;
            end
        join
        
        #500;
        $finish;
    end
    //count
    always @(posedge wclk) begin
        count <= (wr_en==1'b1) ? count + 1 : count ;
    end
    // 实时监控状态信号
    always @(posedge wclk) begin
        $display("[WR] Time: %0t | WrEn: %b | Full: %b AlmostFull: %b",
               $time, wr_en, full, almost_full);
    end
    
    always @(posedge rclk) begin
        $display("[RD] Time: %0t | RdEn: %b | Empty: %b AlmostEmpty: %b",
               $time, rd_en, empty, almost_empty);
    end
endmodule